package gupao.concurrency.simpledemo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

@Slf4j
public class ReplayMockClient {

    static class Task implements Callable<String>{
        private final String uid;
        private final HttpEntity<String> entity;

        private HttpHeaders createHeader(){
            HttpHeaders httpHeaders = new HttpHeaders();
            List<String> cookies = new ArrayList<>();
            cookies.add("suid=" + uid + ";");
            httpHeaders.put(HttpHeaders.COOKIE,cookies);
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            return httpHeaders;
        }

        public Task(String uid) {
            this.uid = uid;
            entity = new HttpEntity<>(createHeader());
        }

        @Override
        public String call() throws Exception {
            ResponseEntity<String> rsp = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
            return rsp.getBody();
        };
    }

    static String url = "http://localhost:8080/replay";

    static RestTemplate restTemplate = new RestTemplate();

    static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws Exception {
//        List<Task> uidList = IntStream.range(0,10).mapToObj(i -> new Task("000" + i)).collect(Collectors.toList());
        Map<String, String> prepareList = prepare2Users("0001","0002"/*,"0003","0004","0005","0006"*/);
        System.out.println("prepare finished:");
//        System.out.println();
        List<String> result007List = oneUserProcess10Times("0007");

        System.out.println("0001~0002 result:");
        prepareList.forEach((uid, result) -> System.out.println(uid + ": " + result));
        System.out.println();
        System.out.println("0007 Result:");
        result007List.forEach(System.out::println);

        executor.shutdownNow();
    }

    private static Map<String, String> prepare2Users(String... users) throws InterruptedException {
        List<Task> uidList = Arrays.stream(users).map(Task::new).collect(Collectors.toList());
        Map<String, Future<String>> map = new HashMap<>();
        uidList.forEach(t -> map.put(t.uid,executor.submit(t)));

//        List<Future<String>> fs = executor.invokeAll(uidList);
        return waitAllFutureFinished(map);
    }

    private static List<String> oneUserProcess10Times(String uid) throws Exception {
        Task user0 = new Task(uid);
        List<String> result = new ArrayList<>();
        for(int i = 0; i < 10; i++){
            result.add(user0.call());
        }
        return (result);
    }

    private static void print(List<String> result){
        result.forEach(log::info);
    }

    private static Map<String, String> waitAllFutureFinished(Map<String,Future<String>> fs){
        Map<String, String> rt = new HashMap<>();
        for(String key : fs.keySet()){
            try {
                Future<String> f = fs.get(key);
                rt.put(key,f.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return rt;
    }

    private static <T> T get(Future<T> f){
        try {
            return f.get();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
